/*
 * AbastractOS
 * Copyright (C) 2011 Davide Gessa
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
#include "AbGui.hpp"
#include "Data/default_font.h"
#include <Driver.hpp>
#include <malloc.h>

unsigned buftest[][1] =
{
	{ 0xA0DB00 },
	{ 0xA2DB00 },
	{ 0xA4DB00 },
	{ 0xA6DB00 },
	{ 0xA8DB00 },
	{ 0xAADB00 },
	{ 0xACDB00 },
	{ 0xAEDB00 },
	{ 0xB0DB00 },
	{ 0xB2DB00 },
	{ 0xB4DB00 },
	{ 0xB6DB00 },
	{ 0xB8DB00 },
	{ 0xBADB00 },
	{ 0xBCDB00 },
	{ 0xBEDB00 },
	{ 0xC0DB00 },
	{ 0xC2DB00 }
};

/** Create de gui driver */
AbGuiDriver::AbGuiDriver() : Driver("AbGui", "abg")
{
}



/** Destroy the gui */
AbGuiDriver::~AbGuiDriver()
{
	
}


/** Gui mainloop */
void
AbGuiDriver::mainLoop()
{
	m_Vesa = (VesaDriver *) Managers::Instance->deviceManager->getDevice("ve0")->getDriver();

	m_RendDim = m_Vesa->getBpp() / 8 * m_Vesa->getX() * m_Vesa->getY();
	m_RendBuf = (char *) malloc(m_RendDim);

	
	vesa_mode_info_t *vmi = m_Vesa->getModeInfo();
	m_Vesa->Memory = (char *) vmi->phys_base_ptr;

	unsigned i = 0xFFFFFF;
	unsigned j = 0;
	while(1)
	{		
		drawLine(120, 120, 150, 170, i);
		drawRect(0, 0, 100, 100, i);

		//for(j = 0; j < m_Vesa->getX(); j++)
		//	drawBuffer((uint32_t *)buftest, j, 0, 1, 18);

			
		drawText("ciaooo", 10, 1, 0xFF);

		swapBuffer();
	}
}


/** Probe the gui */
bool 
AbGuiDriver::Probe() 
{
	bool probe_state;

	VesaDriver *vd = new VesaDriver();
	probe_state = vd->Probe();
	delete(vd);

	return probe_state;
}




/**
 * Swap the buffer in the video ram 
 *
 * \param x0 start in x
 * \param x1 end in x
 * \param y0 start in y
 * \param y1 end in y
 */
void 
AbGuiDriver::swapBuffer(unsigned x0, unsigned y0, unsigned x1, unsigned y1)
{
	if(x0 == x1)
		memcpy(m_Vesa->Memory, m_RendBuf, m_RendDim);
}




/** Draw a pixel */
void 
AbGuiDriver::drawPixel(unsigned x, unsigned y, unsigned cl)
{	
	vesa_mode_info_t *vmi = m_Vesa->getModeInfo();
	
	x = (x * (vmi->bits_per_pixel >> 3));
	y = (y * vmi->bytes_per_scan_line);
	unsigned xy = x + y;

	m_RendBuf[xy] = cl & 0xFF;
	m_RendBuf[xy+1] = (cl >> 8) & 0xFF;
	m_RendBuf[xy+2] = (cl >> 16) & 0xFF;
}



/** Draw a rect */
void 
AbGuiDriver::drawRect(unsigned x0, unsigned y0, unsigned x1, unsigned y1, unsigned cl, bool fill)
{
	unsigned i;

	drawLine(x0, y0, x1, y0, cl);

	if(fill)
	{
		for(i = y0; i < y1; i++)
			drawLine(x0, i, x1, i, cl);
	}
}




/** Draw a text string */
void 
AbGuiDriver::drawText(char *data, unsigned x, unsigned y, unsigned cl, unsigned size)
{
	char *let_data;
			
	unsigned i, j;
	
	while(*data != '\0')
	{
		if(size == 16) 
			let_data = default_font_8x16[(unsigned) (*data)];
		else if(size == 8) 
			let_data = default_font_8x8[(unsigned) (*data)];

		for(i = 0; i < size; i++)
		{
			for(j = 0; j < 8; j++)
			{			
				if((let_data[i] & (1 << j)) > 0)
					drawPixel(x + j, y + i-4, (uint32_t) cl);
			}
		}

		x += 8;
		data++;
	}
}



/** Draw a line */
void 
AbGuiDriver::drawLine(unsigned x0, unsigned y0, unsigned x1, unsigned y1, unsigned cl)
{
	unsigned i, j;
	unsigned factor = (y1 - y0) / (x1 - x0);

	for(i = x0, j = y0; i < x1; i++, j+=factor)
		drawPixel(i, j, cl);
}




/** Draw a buffer */
void 
AbGuiDriver::drawBuffer(uint32_t *data, unsigned x, unsigned y, unsigned dimx, unsigned dimy)
{
	unsigned i, j;

	for(i = 0; i < dimx; i++)
		for(j = 0; j < dimy; j++)
			drawPixel(x + i, y + j, data[j * dimx + i]);
}
